#include "Subsystems/BlockBehaviors/SubsystemChestBlockBehavior.h"
#include "Subsystems/SubsystemBlockEntities.h"

#include "Managers/GameManager.h"
#include "Components/ComponentBlockEntity.h"
#include "Components/ComponentChest.h"

#include "GameSingleton.h"
#include "GameRegistry.hpp"
#include "Log.h"
#include "Blocks/ChestBlock.h"

namespace PocketSurvival
{
    SubsystemChestBlockBehavior::SubsystemChestBlockBehavior()
    {
        m_handleBlocks.push_back(ChestBlock::Index());
    }

    void SubsystemChestBlockBehavior::onBlockAdded(int32_t value, int32_t oldValue, int32_t x, int32_t y, int32_t z)
    {
        Point3 point(x,y,z);
        m_subsystemBlockEntities->addBlockEntity("Chest", point);
    }

	void SubsystemChestBlockBehavior::onBlockRemoved(int32_t value, int32_t newValue, int32_t x, int32_t y, int32_t z)
    {
        m_subsystemBlockEntities->blockEntitiesMutex.lock();
        ComponentBlockEntity *blockEntity = m_subsystemBlockEntities->findBlockEntity(x, y, z);
        if (blockEntity != nullptr)
        {
            Vector3 position(x, y, z);
            position += 0.5f;
            ComponentChest *componentChest = GameSingleton::gameRegistry->get<ComponentChest*>(blockEntity->entity);
            componentChest->dropAllItems(position);
            m_subsystemBlockEntities->removeBlockEntity(blockEntity);
        }
        m_subsystemBlockEntities->blockEntitiesMutex.unlock();
    }

    bool SubsystemChestBlockBehavior::onInteract(const TerrainRaycastResult &raycastResult, ComponentMiner *componentMiner)
    {
        return false;
    }

    void SubsystemChestBlockBehavior::onHitByProjectile(const CellFace &cellFace, WorldItem *worldItem)
    {
        if(worldItem->toRemove)
        {
            return;
        }

        m_subsystemBlockEntities->blockEntitiesMutex.lock();
        ComponentBlockEntity *blockEntity = m_subsystemBlockEntities->findBlockEntity(cellFace.point);
        if (blockEntity != nullptr)
        {
            ComponentChest *componentChest = GameSingleton::gameRegistry->get<ComponentChest*>(blockEntity->entity);
            int32_t count = 1;
            Pickable *pickable = (worldItem->type == WorldItemType::Pickable ? static_cast<Pickable*>(worldItem) : nullptr);
            int32_t num = (pickable == nullptr ? 1 : pickable->count);
            int32_t num2 = componentChest->addItemFast(worldItem->value, num); // ComponentInventoryBase::AcquireItems(componentChest, worldItem->value, num);
            if(num2 <= 0)
            {
                worldItem->toRemove = true;
            }
            else if(pickable != nullptr)
            {
                pickable->count = num2;
            }
        }
        m_subsystemBlockEntities->blockEntitiesMutex.unlock();
    }

    static const std::string subsystemName = "ChestBlockBehavior";
    const std::string& SubsystemChestBlockBehavior::getName() const
    {
        return subsystemName;
    }
    void SubsystemChestBlockBehavior::load(const nlohmann::json &json)
    {
        m_subsystemBlockEntities = GameSingleton::singletonPtr->getSingleton<SubsystemBlockEntities>();
    }
}